Robbie Han

博客不再维护,转https://thinkbucket.cn/

  • 主页
  • Js
  • CSS
  • Node
  • React
  • Web
  • Git
所有文章 友链 关于我

Robbie Han

博客不再维护,转https://thinkbucket.cn/

  • 主页
  • Js
  • CSS
  • Node
  • React
  • Web
  • Git

git merge

2020-04-29

git merge 的几种形式

转载连接

这几天我就遇到了一个问题,其实也不是遇到问题,而是遇到了疑惑,那就是我在 github 系统中 merge 同时的 PR 的时候发现有好几个选项,但是,却说不清楚这几个选项分别代表什么含义,所以就稍微花了点时间了解了下,顺带做个总结。

merge 的几种形式

在 merge pr 的时候,默认是有三种选项的,分别是

  • 普通的 merge
  • rebase merge
  • squash merge

  • 这其实对应于我们在合并分支的时候的几种方式,所以我就以本地分支的形式来说说有啥区别。

    一个简单的模型

    假设我们一开始的 master 分支上已经有了几个提交,就像这样:

    然后,我们切出一条开发的分支,进行了一些 Feature 的开发,然后我们的分支可能就是这种情况:

    这种情况还好,也比较常遇到,但是,现在问题来了,如果在这个时候 master 有了一些新提交(可能是其他分支合并进来的),那么这个时候情形就成了这样:

    这个情况很有趣,但是我们不讨论,因为这和我们今天的主题无关,以后可以另外开一个话题来说,今天要说的是第二个情况。

    普通 Merge

    说到合并分支,可能我们最熟悉的操作是这样的:

    • 先切换到目标分支(master)
    • 执行命令:git merge devel
    • 删除旧分支(可以在上面一同做):git branch -D devel

    • 提交到远程分支:git push origin master

    • 好像这样没啥问题的样子,但是这样操作之后,你知道结果是怎么样吗?假设合并之前的这样的:

      15101478786848

      我们这么一番操作之后,那么最后我们的分支的历史将会是这样的:

      是的,看上去很不错,也是一条直直的 commit line,我们在 devel 分支中的 commit 也是一个不差得保留在了 master 中。但是,很多时候,我们并不需要那么多的 commit,假设你给一个开源项目提交一个 Bug Fixes,然后一个简单的修改因为你的粗心大意 pr 了十几个 commit 过去,如果作者给你 merge 了,这就在这个项目的历史长河中增加了十几个 commit 啊,以后的人看 commit history 估计都崩溃了吧;同时,对于你自己管理的项目来说,当你 merge 之后发现有问题,想回滚都蛋疼!

      squash merge

      在使用 git 的过程中,可能你遇到过想要合并多个 commit 为一个,然后很多人会告诉你用 git commit –amend,然后你发现里面有你的多个 commit 历史,你可以通过 pick 选择,squash 合并等等。同样得,merge 的时候也可以这么干,你只需要这么简单的两步:

      • 切换到目标分支:git checkout master
      • 以 squash 的形式 merge:git merge –squash devel

      • 你会发现,在 master 分支上居然有未提交的修改,然后你就需要在 master 上主动提交了修改,注意,这里是你 commit 的,也就是改变了 commit 的 author。结果是这样的:

        这里好了,比前面普通的 merge 来说,我们只有一个 commit 了,不管在分支中 commit 了多少,这里都只有一个!

        rebase merge

        但是,作为处女座的程序员肯定是不能忍受目前的情况的,因为我们既想合并 commits,又想保留作者的信息,那么有没有什么好办法呢?肯定是有的啦,这个时候我们可以尝试一下 rebase,操作步骤是这样的:

        • 先切换到 devel 分支(不一样咯):git checkout devel
        • 变基:git rebase -i master
        • 切换回目标分支:git checkout master
        • 合并: git merge devel

        • 这里完成了第二步之后我想你应该大概知道发生了什么事了,我们在 devel 里面对照 master 进行了变基,所谓的变基其实就是找到两个分支共同的祖先,然后在当前分支上合并从共同祖先到现在的所有 commit,所以我们在第二步的时候会选择怎么处理这些 commit,然后我们就得到了一个从公共commit 到现在的单个 commit,这个时候别人讲我们这个 commit 合并到 master 也只会在 master 上留下一个 commit 记录,就像这样:

          虽然这个 commit history 线看上去很不错,而且也比较符合实际情况,但是我们需要注意到的有点就是分支上的开发者需要自己执行变基操作,从而导致他的原始 commit history 变化了(可以理解成被合并了)。

          对比

          相比一下前面三种方式,我们可以总结出一些东西:


          1. rebase 可以尽可能保持 master 分支干净整洁,并且易于识别 author

          2. squash 也可以保持 master 分支干净,但是 master 中 author 都是 maintainer,而不是原 owner

          3. merge 不能保持 master 分支干净,但是保持了所有的 commit history,大多数情况下都是不好的,个别情况挺好


          所以,相比这么多,我是推荐使用 rebase 的,但是,当你在使用过程中,你会发现它的要求有点高,[/手动哭脸]


          Reference



          1. Pro Git

          2. In git, what is the difference between merge –squash and rebase?

          赏

          谢谢你请我吃糖果

          • Git

          扫一扫,分享到微信

          微信分享二维码
          http缓存
          Emoji
          © 2020 Robbie Han
          Hexo Theme Yilia by Litten
          • 所有文章
          • 友链
          • 关于我

          tag:

          • JS
          • Array
          • flat
          • 闭包
          • 内存泄漏
          • babel
          • CSS
          • width:auto
          • width:100%
          • Web
          • 页面渲染
          • DOMContentLoaded
          • load
          • Git
          • 深拷贝
          • 深比较
          • _.isEqual()
          • 变量互换
          • Math
          • 开发工具
          • PicGo
          • Markdown
          • Object.create()
          • new Object()
          • Promise
          • H5
          • webSocket
          • web Worker
          • Async
          • flex
          • align-items
          • align-content
          • React
          • Redux
          • [object Object]
          • for...in
          • for...of
          • http 缓存
          • Iterable
          • immutable
          • location
          • max-hight
          • min-hight
          • Node
          • number
          • npm link
          • create-react-app
          • parseInt
          • Promis.all()
          • replace
          • String
          • rooter
          • 路由
          • DNS
          • 三次握手
          • 四次挥手
          • 前序遍历
          • 中序遍历
          • 后序遍历
          • 层次遍历
          • 链式调用
          • ASCALL
          • margin合并
          • BFC
          • 宏任务
          • 微任务
          • 水平居中
          • 垂直居中
          • 水平垂直居中
          • 工具
          • 数组
          • 交集
          • 并集
          • 柯理化
          • 浏览器内核
          • 进程
          • 线程
          • 类数组对象
          • 继承
          • 节流
          • 滚动加载
          • 重新思考setTimeout
          • 事件循环
          • setTimeout
          • setInterval
          • 时间循环
          • 防抖

            缺失模块。
            1、请确保node版本大于6.2
            2、在博客根目录(注意不是yilia根目录)执行以下命令:
            npm i hexo-generator-json-content --save

            3、在根目录_config.yml里添加配置:

              jsonContent:
                meta: false
                pages: false
                posts:
                  title: true
                  date: true
                  path: true
                  text: false
                  raw: false
                  content: false
                  slug: false
                  updated: false
                  comments: false
                  link: false
                  permalink: false
                  excerpt: false
                  categories: false
                  tags: true
            

          • 友情链接1
          • 友情链接2
          • 友情链接3
          • 友情链接4
          • 友情链接5
          • 友情链接6
          很惭愧<br><br>只做了一点微小的工作<br>谢谢大家